﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Windows.Forms;
using Work.API.Applications.Write.Commands;
using Work.API.Dtos;

namespace WinFormsApp1
{
    /// <summary>
    /// 门诊结账表单
    /// </summary>
    public partial class OutpatientSettlementForm : Form
    {
        private const string ApiBaseUrl = "http://localhost:5044";
        private readonly HttpClient _httpClient;
        private readonly JsonSerializerOptions _jsonOptions;
        private List<UnpaidPatientDto> _unpaidPatients;
        private List<PrescriptionItemDto> _currentPrescriptionItems;
        private PatientBillDto? _currentPatientBill;
        private SettlementSummaryDto? _currentSettlement;

        public OutpatientSettlementForm()
        {
            InitializeComponent();
            _httpClient = new HttpClient { BaseAddress = new Uri(ApiBaseUrl) };
            _jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
            _unpaidPatients = new List<UnpaidPatientDto>();
            _currentPrescriptionItems = new List<PrescriptionItemDto>();
            
            LoadUnpaidPatients();
        }

        private async void LoadUnpaidPatients()
        {
            try
            {
                var response = await _httpClient.GetAsync("api/OutpatientSettlement/GetUnpaidPatients");
                response.EnsureSuccessStatusCode();
                var json = await response.Content.ReadAsStringAsync();
                var apiResult = JsonSerializer.Deserialize<ApiResult<List<UnpaidPatientDto>>>(json, _jsonOptions);

                if (apiResult != null && apiResult.Code == 100 && apiResult.Data != null)
                {
                    _unpaidPatients = apiResult.Data;
                    RefreshUnpaidPatientsGrid();
                    
                    // 默认选择第一条未付款病人
                    if (_unpaidPatients.Count > 0)
                    {
                        SelectFirstUnpaidPatient();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载未支付患者失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void RefreshUnpaidPatientsGrid()
        {
            dgvUnpaidPatients.DataSource = null;
            dgvUnpaidPatients.DataSource = _unpaidPatients.Select(p => new
            {
                挂单号 = p.RegistrationNum,
                名字 = p.PatientName,
                性别 = p.GenderText,
                科室 = p.Department,
                身份证 = p.IdCard,
                AppointmentId = p.AppointmentId
            }).ToList();

            if (dgvUnpaidPatients.Columns.Contains("AppointmentId"))
                dgvUnpaidPatients.Columns["AppointmentId"].Visible = false;
        }

        private async void SelectFirstUnpaidPatient()
        {
            // 等待DataGridView完全绑定数据
            await System.Threading.Tasks.Task.Delay(50);
            
            if (dgvUnpaidPatients.Rows.Count > 0)
            {
                var firstRow = dgvUnpaidPatients.Rows[0];
                if (firstRow.Cells["AppointmentId"].Value != null)
                {
                    var appointmentId = (int)firstRow.Cells["AppointmentId"].Value;
                    
                    // 选中第一行
                    dgvUnpaidPatients.ClearSelection();
                    firstRow.Selected = true;
                    dgvUnpaidPatients.CurrentCell = firstRow.Cells[0];
                    dgvUnpaidPatients.FirstDisplayedScrollingRowIndex = 0;
                    
                    // 加载患者信息
                    await LoadPatientBill(appointmentId);
                }
            }
        }

        private async System.Threading.Tasks.Task LoadPatientBill(int appointmentId)
        {
            try
            {
                var response = await _httpClient.GetAsync($"api/OutpatientSettlement/GetPatientBill?appointmentId={appointmentId}");
                response.EnsureSuccessStatusCode();
                var json = await response.Content.ReadAsStringAsync();
                var apiResult = JsonSerializer.Deserialize<ApiResult<PatientBillDto>>(json, _jsonOptions);

                if (apiResult != null && apiResult.Code == 100 && apiResult.Data != null)
                {
                    _currentPatientBill = apiResult.Data;
                    FillPatientInfo();
                    await LoadPrescriptionItems(appointmentId);
                    await CalculateTotalAmount(appointmentId);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载患者信息失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void FillPatientInfo()
        {
            if (_currentPatientBill == null) return;

            txtRegistrationNum.Text = _currentPatientBill.RegistrationNum;
            txtPatientName.Text = _currentPatientBill.PatientName;
            cmbGender.Text = _currentPatientBill.GenderText;
            txtDepartment.Text = _currentPatientBill.Department;
            txtDoctorName.Text = _currentPatientBill.DoctorName;
            txtIdCard.Text = _currentPatientBill.IdCard;
        }

        private async System.Threading.Tasks.Task LoadPrescriptionItems(int appointmentId)
        {
            try
            {
                var response = await _httpClient.GetAsync($"api/Prescription/GetByAppointment?appointmentId={appointmentId}&unpaidOnly=true");
                response.EnsureSuccessStatusCode();
                var json = await response.Content.ReadAsStringAsync();
                var apiResult = JsonSerializer.Deserialize<ApiResult<List<PrescriptionItemDto>>>(json, _jsonOptions);

                if (apiResult != null && apiResult.Code == 100 && apiResult.Data != null)
                {
                    _currentPrescriptionItems = apiResult.Data;
                    RefreshPrescriptionItemsGrid();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载药品明细失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void RefreshPrescriptionItemsGrid()
        {
            dgvPrescriptionItems.DataSource = null;
            
            // 创建消费明细列表，包含挂号费、其他费用和药品信息
            var consumptionItems = new List<object>();
            
            // 添加挂号费（如果有）
            if (_currentSettlement != null && _currentSettlement.RegistrationFee > 0)
            {
                consumptionItems.Add(new
                {
                    药品名称 = "挂号费",
                    药品单价 = _currentSettlement.RegistrationFee.ToString("F2"), // 格式化为两位小数
                    数量 = 1
                });
            }
            
            // 添加其他费用（如果有）
            if (_currentSettlement != null && _currentSettlement.OtherFee > 0)
            {
                consumptionItems.Add(new
                {
                    药品名称 = "其他费用",
                    药品单价 = _currentSettlement.OtherFee.ToString("F2"), // 格式化为两位小数
                    数量 = 1
                });
            }
            
            // 添加未支付的药品（双重保险，API已经过滤，这里再次确保）
            var unpaidItems = _currentPrescriptionItems
                .Where(item => item.PaymentStatus == "未支付" || string.IsNullOrEmpty(item.PaymentStatus))
                .ToList();
            
            // 将药品信息添加到列表，价格格式化为两位小数
            var medicineItems = unpaidItems.Select(item => new
            {
                药品名称 = item.MedicineName,
                药品单价 = item.UnitPrice.ToString("F2"), // 格式化为两位小数
                数量 = item.Quantity
            }).ToList();
            
            consumptionItems.AddRange(medicineItems);
            
            // 绑定数据源
            dgvPrescriptionItems.DataSource = consumptionItems;
        }

        private async System.Threading.Tasks.Task CalculateTotalAmount(int appointmentId)
        {
            try
            {
                var response = await _httpClient.GetAsync($"api/OutpatientSettlement/CalculateTotalAmount?appointmentId={appointmentId}");
                response.EnsureSuccessStatusCode();
                var json = await response.Content.ReadAsStringAsync();
                var apiResult = JsonSerializer.Deserialize<ApiResult<SettlementSummaryDto>>(json, _jsonOptions);

                if (apiResult != null && apiResult.Code == 100 && apiResult.Data != null)
                {
                    _currentSettlement = apiResult.Data;
                    txtTotalAmount.Text = _currentSettlement.TotalAmount.ToString("F2");
                    
                    // 刷新消费明细列表，以显示挂号费和其他费用
                    RefreshPrescriptionItemsGrid();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"核算总金额失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSearch_Click(object? sender, EventArgs e)
        {
            var idCard = txtSearchIdCard.Text.Trim();

            if (string.IsNullOrWhiteSpace(idCard))
            {
                MessageBox.Show("请输入身份证号", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            SearchAndLoadPatientByExactIdCard(idCard);
        }

        private async void SearchAndLoadPatientByExactIdCard(string idCard)
        {
            try
            {
                // 使用精确查询（使用GetPatientBill接口进行精确匹配）
                var response = await _httpClient.GetAsync($"api/OutpatientSettlement/GetPatientBill?idCard={Uri.EscapeDataString(idCard)}");
                response.EnsureSuccessStatusCode();
                var json = await response.Content.ReadAsStringAsync();
                var apiResult = JsonSerializer.Deserialize<ApiResult<PatientBillDto>>(json, _jsonOptions);

                if (apiResult != null && apiResult.Code == 100 && apiResult.Data != null)
                {
                    // 检查该患者是否在未支付列表中
                    var foundPatient = _unpaidPatients.FirstOrDefault(p => p.IdCard == idCard);
                    
                    if (foundPatient != null)
                    {
                        await LoadPatientBill(foundPatient.AppointmentId);

                        // 高亮显示
                        for (int i = 0; i < dgvUnpaidPatients.Rows.Count; i++)
                        {
                            if (dgvUnpaidPatients.Rows[i].Cells["AppointmentId"].Value?.ToString() == foundPatient.AppointmentId.ToString())
                            {
                                dgvUnpaidPatients.Rows[i].Selected = true;
                                dgvUnpaidPatients.CurrentCell = dgvUnpaidPatients.Rows[i].Cells[0];
                                dgvUnpaidPatients.FirstDisplayedScrollingRowIndex = i;
                                break;
                            }
                        }
                    }
                    else
                    {
                        MessageBox.Show("该患者不在未支付列表中", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                else
                {
                    MessageBox.Show("未找到符合条件的患者", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"查询失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async void btnCalculate_Click(object? sender, EventArgs e)
        {
            if (_currentPatientBill == null)
            {
                MessageBox.Show("请先选择患者", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            await CalculateTotalAmount(_currentPatientBill.AppointmentId);
        }

        private void txtPaymentAmount_TextChanged(object? sender, EventArgs e)
        {
            CalculateChange();
        }

        private void CalculateChange()
        {
            if (_currentSettlement == null) return;

            if (decimal.TryParse(txtPaymentAmount.Text, out var paidAmount))
            {
                var change = paidAmount - _currentSettlement.TotalAmount;
                txtChange.Text = change >= 0 ? change.ToString("F2") : "0.00";
            }
            else
            {
                txtChange.Text = "0.00";
            }
        }

        private async void btnSettle_Click(object? sender, EventArgs e)
        {
            if (_currentPatientBill == null || _currentSettlement == null)
            {
                MessageBox.Show("请先选择患者并核算总金额", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (!decimal.TryParse(txtPaymentAmount.Text, out var paidAmount) || paidAmount < _currentSettlement.TotalAmount)
            {
                MessageBox.Show("支付金额不足", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (MessageBox.Show("确定要结算吗？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
            {
                return;
            }

            btnSettle.Enabled = false;

            try
            {
                var command = new SettlePaymentCommand
                {
                    AppointmentId = _currentPatientBill.AppointmentId,
                    PatientId = _currentPatientBill.PatientId,
                    RegistrationNum = _currentPatientBill.RegistrationNum,
                    TotalAmount = _currentSettlement.TotalAmount,
                    PaidAmount = paidAmount,
                    PaymentMethod = "现金",
                    InvoicePrinted = false  // 打印发票功能单独处理
                };

                var json = JsonSerializer.Serialize(command);
                using var content = new StringContent(json, Encoding.UTF8, "application/json");
                var response = await _httpClient.PostAsync("api/OutpatientSettlement/Settle", content);
                response.EnsureSuccessStatusCode();
                var respJson = await response.Content.ReadAsStringAsync();
                var apiResult = JsonSerializer.Deserialize<ApiResult<int>>(respJson, _jsonOptions);

                if (apiResult != null && apiResult.Code == 100)
                {
                    MessageBox.Show("结算成功", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    
                    // 清空当前选择
                    ClearCurrentSelection();
                    
                    // 重新加载未支付患者列表（会自动选择第一条）
                    LoadUnpaidPatients();
                }
                else
                {
                    MessageBox.Show(apiResult?.Message ?? "结算失败", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"结算失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                btnSettle.Enabled = true;
            }
        }

        private void btnPrintInvoice_Click(object? sender, EventArgs e)
        {
            if (_currentPatientBill == null)
            {
                MessageBox.Show("请先选择患者", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (_currentSettlement == null)
            {
                MessageBox.Show("请先核算总金额", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 检查是否已结算（如果患者在未支付列表中，说明未结算，不能打印）
            var appointment = _unpaidPatients.FirstOrDefault(p => p.AppointmentId == _currentPatientBill.AppointmentId);
            if (appointment != null)
            {
                MessageBox.Show("请先完成结算，然后再打印发票", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 如果没有支付金额信息，提示用户
            if (string.IsNullOrWhiteSpace(txtPaymentAmount.Text))
            {
                MessageBox.Show("请先完成结算并输入支付金额", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 这里实现打印发票的功能
            // 可以调用打印对话框或直接打印
            try
            {
                // 构建发票内容
                var invoiceContent = $"========== 门诊收费发票 ==========\n" +
                                   $"挂单号：{_currentPatientBill.RegistrationNum}\n" +
                                   $"患者姓名：{_currentPatientBill.PatientName}\n" +
                                   $"性别：{_currentPatientBill.GenderText}\n" +
                                   $"身份证号：{_currentPatientBill.IdCard}\n" +
                                   $"科室：{_currentPatientBill.Department}\n" +
                                   $"主治医生：{_currentPatientBill.DoctorName}\n" +
                                   $"-----------------------------------\n" +
                                   $"总金额：{_currentSettlement.TotalAmount:F2} 元\n" +
                                   $"支付金额：{txtPaymentAmount.Text} 元\n" +
                                   $"找零：{txtChange.Text} 元\n" +
                                   $"-----------------------------------\n";

                // 添加药品明细
                if (_currentPrescriptionItems != null && _currentPrescriptionItems.Count > 0)
                {
                    invoiceContent += "药品明细：\n";
                    foreach (var item in _currentPrescriptionItems)
                    {
                        invoiceContent += $"{item.MedicineName}  {item.UnitPrice:F2}元 x {item.Quantity} = {item.TotalAmount:F2}元\n";
                    }
                }

                invoiceContent += $"打印时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss}\n";
                invoiceContent += "===================================\n";

                // 显示发票预览（实际项目中可以使用打印对话框）
                MessageBox.Show(invoiceContent, "发票预览", MessageBoxButtons.OK, MessageBoxIcon.Information);

                // 如果需要实际打印，可以使用PrintDocument
                // var printDocument = new PrintDocument();
                // printDocument.PrintPage += (s, args) => {
                //     args.Graphics.DrawString(invoiceContent, new Font("Arial", 12), Brushes.Black, 100, 100);
                // };
                // printDocument.Print();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打印发票失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void ClearCurrentSelection()
        {
            _currentPatientBill = null;
            _currentSettlement = null;
            _currentPrescriptionItems.Clear();

            txtRegistrationNum.Text = "";
            txtPatientName.Text = "";
            cmbGender.Text = "";
            txtDepartment.Text = "";
            txtDoctorName.Text = "";
            txtIdCard.Text = "";
            txtTotalAmount.Text = "";
            txtPaymentAmount.Text = "";
            txtChange.Text = "";
            dgvPrescriptionItems.DataSource = null;
        }

        private void btnCancel_Click(object? sender, EventArgs e)
        {
            this.Close();
        }

        private async void dgvUnpaidPatients_CellClick(object? sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                var row = dgvUnpaidPatients.Rows[e.RowIndex];
                if (row.Cells["AppointmentId"].Value != null)
                {
                    var appointmentId = (int)row.Cells["AppointmentId"].Value;
                    await LoadPatientBill(appointmentId);
                }
            }
        }

        private class ApiResult<T>
        {
            public int Code { get; set; }
            public string? Message { get; set; }
            public T? Data { get; set; }
        }
    }
}

